//封装一个UdpSocket
#pragma once
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<string>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
typedef struct sockaddr sockaddr;
typedef struct sockaddr_in sockaddr_in;
class UdpSocket{
    public:
    UdpSocket():_fd(-1) {}
    ~UdpSocket(){
        Close();
    }
    bool Close(){
        if(_fd!=-1){
            close(_fd);
            _fd=-1;     //关闭并重置文件描述符
        }
        return true;
    }
    bool Socket(){
        _fd=socket(AF_INET,SOCK_DGRAM,0);
        if(_fd==-1){
            std::cout<<"socket error\n";
            return false;
        }
        return true;
    }
    bool Bind(u_int16_t port,std::string ip="0.0.0.0"){
        sockaddr_in addr;
        addr.sin_family=AF_INET;
        addr.sin_port=htons(port);
        if (ip == "0.0.0.0" || ip.empty()) {
            addr.sin_addr.s_addr = INADDR_ANY;  // 正确的用法
        } else {
            addr.sin_addr.s_addr = inet_addr(ip.c_str());
        }

        int n=bind(_fd,(sockaddr*)&addr,sizeof(sockaddr));
        if(n==-1){
            std::cout<<"bind error\n";
            return false;
        }
        return true;
    }
    bool Recvfrom(std::string* buffer,std::string* ip=NULL,u_int16_t* port=NULL){
        char tmp[1024]={0};
        struct sockaddr_in peer;
        memset(&peer,0,sizeof(peer));
        socklen_t len=sizeof(peer);
        ssize_t read_size=recvfrom(_fd,tmp,sizeof(tmp)-1,0,(sockaddr*)&peer,&len);
        if(read_size==-1){
            std::cerr<<"recvfrom error\n";
            return false;
        }

        buffer->assign(tmp,read_size);
        if(ip!=NULL){
            *ip=inet_ntoa(peer.sin_addr);
        }
        if(port!=NULL){
            *port=ntohs(peer.sin_port);
        }
        // std::cout<<"clinet_ip:"<<*ip<<" client_port:"<<port<<std::endl;
        return true;
    }
    bool Sendto(std::string& buf,std::string& ip,u_int16_t port){
        struct sockaddr_in addr;
        addr.sin_family=AF_INET;
        addr.sin_addr.s_addr=inet_addr(ip.c_str());
        addr.sin_port=htons(port);

        ssize_t send_size=sendto(_fd,buf.c_str(),buf.size(),0,(sockaddr*)&addr,sizeof(addr));
        if(send_size==-1){
            std::cerr<<"sendto error\n";
            return false;
        }
        return true;
    }

    private:
    int _fd;
};